//
//  Utils.cpp
//  client
//
//  Created by DuanHongbo on 15/5/13.
//
//

#include "Utils.h"
#include "cocos2d.h"
#include "renderer/CCTexture2D.h"
#include "base/CCAsyncTaskPool.h"
#include "platform/CCCommon.h"
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#include "UtilsNative.h"
#endif

USING_NS_CC;

void onCaptureScreen(const std::function<void(bool, Texture2D*)>& afterCaptured,const std::string& )
{
    static bool startedCapture = false;
    if (startedCapture)
    {
        CCLOG("Screen capture is already working");
        if (afterCaptured)
        {
            afterCaptured(false, nullptr);
        }
        return;
    }
    else
    {
        startedCapture = true;
    }
    
    auto glView = Director::getInstance()->getOpenGLView();
    auto frameSize = glView->getFrameSize();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
    frameSize = frameSize * glView->getFrameZoomFactor() * glView->getRetinaFactor();
#endif
    
    int width = static_cast<int>(frameSize.width);
    int height = static_cast<int>(frameSize.height);
    
    bool succeed = false;
    std::string outputFile = "";
    Texture2D* texture = nullptr;
    
    do
    {
        std::shared_ptr<GLubyte> buffer(new GLubyte[width * height * 4], [](GLubyte* p){ CC_SAFE_DELETE_ARRAY(p); });
        if (!buffer)
        {
            break;
        }
        
        glPixelStorei(GL_PACK_ALIGNMENT, 1);
        glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer.get());
        
        std::shared_ptr<GLubyte> flippedBuffer(new GLubyte[width * height * 4], [](GLubyte* p) { CC_SAFE_DELETE_ARRAY(p); });
        if (!flippedBuffer)
        {
            break;
        }
        
        
        for (int row = 0; row < height; ++row)
        {
            memcpy(flippedBuffer.get() + (height - row - 1) * width * 4, buffer.get() + row * width * 4, width * 4);
        }
        
        Image* image = new (std::nothrow) Image();
        if (image)
        {
            image->initWithRawData(flippedBuffer.get(), width * height * 4, width, height, 8);
            texture = new (std::nothrow) Texture2D();
            texture->initWithImage(image);
            texture->autorelease();
#if CC_ENABLE_CACHE_TEXTURE_DATA
            /*
            AsyncTaskPool::getInstance()->enqueue(AsyncTaskPool::TaskType::TASK_IO, [](void*){}, nullptr, [image]() {
                image->saveToFile(FileUtils::getInstance()->getWritablePath()+"custom-screen-shot.jpg",true);
            });
            // cache the texture file name
            VolatileTextureMgr::addImageTexture(texture,FileUtils::getInstance()->getWritablePath()+"custom-screen-shot.jpg");
             */
            VolatileTextureMgr::addImage(texture,image);
#endif
            image->autorelease();
            succeed = true;
        }
        else
        {
            CCLOG("Malloc Image memory failed!");
            succeed = false;
        }
    }while(0);
    
    if (afterCaptured)
    {
        afterCaptured(succeed, texture);
    }
    startedCapture = false;
}


void Utils::captureScreen(const std::function<void(bool, Texture2D*)>& afterCaptured)
{
    static CustomCommand captureScreenCommand;
    captureScreenCommand.init(std::numeric_limits<float>::max());
    captureScreenCommand.func = std::bind(onCaptureScreen, afterCaptured,"");
    Director::getInstance()->getRenderer()->addCommand(&captureScreenCommand);
}

void Utils::showMessageBox(const char * title, const char * content)
{
	MessageBox(content, title);
}


#if CC_TARGET_PLATFORM != CC_PLATFORM_MAC
std::vector<std::string> Utils::getCommandLineParam()
{
	std::vector<std::string> vec;
#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
	for (int i = 0; i < __argc; ++i)
    {
		std::wstring ws(__wargv[i]);
		std::string s;
		s.assign(ws.begin(), ws.end());
		vec.push_back(s);
	}
#endif
	return vec;
}
#endif

void Utils::setTextureHalfSizeEnable(bool enbale)
{
    cocos2d::Texture2D::setTextureHalfSizeEnable(enbale);
}

void Utils::addTextureHalfFilterRegex(const char * filterRegex)
{
    cocos2d::Texture2D::addHalfSizeFilterRegex(filterRegex);
}

void Utils::addTextureHalfIgnoreFilter(const char *filterPath)
{
    cocos2d::Texture2D::addHalfSizeIgnoreFilter(filterPath);
}

bool Utils::checkStringIsEndWith(std::string& strSource, std::string& strCheck)
{
    size_t sourceSize = strSource.size();
    size_t checkSize = strCheck.size();
    if(sourceSize > checkSize)
    {
        return strSource.substr(sourceSize - checkSize) == strCheck;
    }
    else if(sourceSize == checkSize)
    {
        return strSource == strCheck;
    }
    return false;
}

std::string Utils::getGpuInfo()
{
    std::string gpuInfo = (const char *)glGetString(GL_RENDERER);
    return gpuInfo;
}

std::string Utils::getCpuInfo()
{
    std::string cpuInfo;
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
    
#elif CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
    
#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
    
#elif CC_TARGET_PLATFORM == CC_PLATFORM_IOS
    cpuInfo = UtilsNative::getCpuInfo();
#endif
    return cpuInfo;
}

float Utils::getTotalMemoryGB()
{
    float totalMemoryGB = 0.0f;
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
    
#elif CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
    
#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
    
#elif CC_TARGET_PLATFORM == CC_PLATFORM_IOS
    totalMemoryGB = UtilsNative::getTotalMemoryGB();
#endif
    return totalMemoryGB;
}

std::string Utils::getTotalMemoryInfo()
{
    std::string totalMemoryInfo;
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
    
#elif CC_TARGET_PLATFORM == CC_PLATFORM_WIN32
    
#elif CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
    
#elif CC_TARGET_PLATFORM == CC_PLATFORM_IOS
    totalMemoryInfo = UtilsNative::getTotalMemoryInfo();
#endif
    return totalMemoryInfo;
}
